home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / progjrn / pj_6_6.arc / DDI.C < prev    next >
C/C++ Source or Header  |  1988-10-18  |  11KB  |  494 lines

  1. /*
  2. * DDI - Device information program
  3. *
  4. * Written By:    Steve Rodgers
  5. * Conception:    5-4-86
  6. *
  7. * Copyright (C) 1987 Steve Rodgers
  8. *
  9. *
  10. * Functional Description
  11. * ----------------------
  12. *
  13. * This program displays information about installable device drivers
  14. * loaded under DOS 2.0 or later. If the command is typed without any
  15. * arguments, a summary will be printed which shows the order of the devices
  16. * in the chain. If a device name is typed following the command, detailed
  17. * information pertinent to that device will be displayed. This program
  18. * works with either character or block devices as arguments.
  19. *
  20. *
  21. * Revision History
  22. * ----------------
  23. *
  24. * First Release Version 0.1 released 5-7-86
  25. * Second Release Version 0.2 released 3-12-87
  26. * Third Release Version 1.0 released 2-18-88
  27. *
  28. * Compilation instructions
  29. * ------------------------
  30. *
  31. * Use the Microsoft C compiler version 3.00 or later.
  32. * Compile with the -Zp switch.
  33. * Dependencies
  34. * ------------
  35. *
  36. * This module requires the following include files:
  37. *
  38. * stdio.h 
  39. * dos.h    
  40. * string.h
  41. *
  42. *
  43. * Linking instructions
  44. * --------------------
  45. *
  46. * Use the Microsoft linker version 3.00 or later.
  47. *
  48. * LINK COMMAND LINE : link di;
  49. *
  50. *
  51. */
  52.  
  53. #include <stdio.h>
  54. #include <dos.h>
  55. #include <string.h>
  56.  
  57. /*
  58. * Device attribute definitions
  59. */
  60.  
  61. #define    CHARACTER_DEVICE    0x8000
  62. #define IOCTL_SUPPORT        0x4000
  63. #define NON_IBM_FORMAT        0x2000
  64. #define OPEN_CLOSE_SUPPORT    0x800
  65. #define    IS_CLOCK        8
  66. #define IS_NUL            4
  67. #define IS_STDIN        2
  68. #define IS_STDOUT        1
  69.  
  70. /*
  71. * Structure definitions
  72. *
  73. *
  74. * Device header
  75. */
  76.  
  77. struct DEV_HDR
  78.     {
  79.     struct DEV_HDR far    *next_hdr ;    /* pointer next device header */
  80.     unsigned int        attribute ;    /* attribute bits */
  81.     unsigned int        strategy ;    /* strategy offset */
  82.     unsigned int        interruptx ;    /* interrupt offset */
  83.     unsigned char        name[8] ;    /* device name */
  84.     } ;
  85.  
  86. /*
  87. * Disk Parameter Block - Returned by DOS function 32H
  88. */
  89.  
  90. struct DPB
  91.     {
  92.     unsigned char        ad ;        /* current assigned disk */
  93.     unsigned char        alt_ad ;    /* alternate assigned disk */
  94.     unsigned int        bps ;        /* bytes per sector */
  95.     unsigned char        last_sic ;    /* max sector addr in a cluster */
  96.     unsigned char        last_head ;    /* max useable head address */
  97.     unsigned int        rs ;        /* total reserved sectors */
  98.     unsigned char        cf ;        /* copies of the FAT */
  99.     unsigned int        d ;        /* max root directory entries */
  100.     unsigned int        fus ;        /* first useable sector */
  101.     unsigned int        tccplusone ;    /* total clusters available + 1 */
  102.     unsigned char        spf ;        /* sectors per FAT */
  103.     unsigned int        fds ;        /* first directory sector */
  104.     struct DEV_HDR far    *dda ;        /* device driver address */
  105.     unsigned char        md ;        /* media discriptor */
  106.     struct DISK_DPB far    *next_dpb ;    /* address of next dpb in chain */
  107.     unsigned int        cwd_cluster ;     /* cluster of CWD (DOS 2.x only) */
  108.     unsigned char        cwd_string[64] ; /* CWD string (DOS 2.x only) */
  109.     } ;
  110.  
  111. /*
  112. * Function declarations
  113. */
  114.  
  115. struct DPB far *disk_dpb() ;
  116. struct DEV_HDR far *device_chain() ;
  117.  
  118. /*
  119. * Static Declarations
  120. */
  121.  
  122. union REGS ir,or ;
  123. struct SREGS sr ;
  124.  
  125. int is_disk = 0 ;
  126.  
  127. /*
  128. * Attribute bit table
  129. */
  130.  
  131. int attr_bit_masks[] = {CHARACTER_DEVICE,IOCTL_SUPPORT,NON_IBM_FORMAT,
  132.             OPEN_CLOSE_SUPPORT,IS_CLOCK,IS_NUL,IS_STDIN,IS_STDOUT};
  133.  
  134. /*
  135. * Global pointer variables 
  136. */
  137.  
  138. struct DEV_HDR far *current_device, far *previous_device ;
  139. struct DPB far *current_dpb ;
  140.  
  141. /*
  142. * Global device type counters
  143. */
  144.  
  145. int block_drivers = 0,character_drivers = 0 ;
  146.  
  147. /*
  148. * Function: main()
  149. */
  150.  
  151. main(argc,argv)
  152. int argc ;
  153. char *argv[] ;
  154. {
  155.     int i ;
  156.     char *device_name ;
  157.  
  158.     printf("\nDDI   -              Device Driver Information Program\n") ;
  159.     printf("Version 1.0 (2-18-88) Copyright (C) 1988 Steve Rodgers\n\n") ;
  160.  
  161.     if(argc < 2) /* if no argument, print the device list */ 
  162.     {
  163.         list_devices() ;
  164.         exit(0) ;
  165.     }
  166.  
  167.     if((device_name = strupr(strdup(argv[1]))) == NULL)
  168.         abort() ;
  169.     print_single_device(device_name) ;
  170. }
  171.  
  172. /*
  173. * Function: print_single_device() 
  174. *
  175. * Print information for a single device.
  176. */
  177.  
  178. print_single_device(device_name)
  179. char device_name[] ;
  180.     int i ;
  181.  
  182. /*
  183. *
  184. * Function: get_device() ;
  185. *
  186. * Get pointer for a specific device.
  187. * If it doesn't exist print an error message.
  188. */
  189.  
  190.     get_device(device_name) ;
  191.     if(current_device == NULL)
  192.     {
  193.         printf("No such device: %s\n",device_name) ;
  194.         exit(1) ;
  195.     }
  196.  
  197. /*
  198. * Print the device address, type, and name.
  199. */
  200.  
  201.     print_device_columns() ;
  202.     print_device_info(current_device) ;
  203.  
  204. /*
  205. * Print the detailed information for the device
  206. */
  207.  
  208.     printf("\n") ;
  209.     printf("                          A T T R I B U T E S\n") ;
  210.     printf("------------------------------------------------------------------------\n") ;
  211.     printf("| CHAR   | IOCTL  | NONIBM | OPNCLS | STDCLK | NULDEV | STDOUT | STDIN |\n") ;
  212.     for(i = 0 ; i < 8 ; i++)
  213.     {
  214.         printf("   ") ;
  215.         if((attr_bit_masks[i] & current_device->attribute))
  216.             printf("yes   ") ;
  217.         else
  218.             printf("no    ") ;
  219.     }
  220.     printf("\n\n") ;
  221.     printf("Strategy entry point\t\t: %04X:%04X\n",
  222.             FP_SEG(current_device),
  223.             current_device->strategy) ;
  224.     
  225.     printf("Interrupt entry point\t\t: %04X:%04X\n",
  226.             FP_SEG(current_device),
  227.             current_device->interruptx) ;
  228.  
  229. /*
  230. * Return to DOS
  231. */
  232.  
  233.     exit(0) ;
  234. }
  235.  
  236. /*
  237. * Function: list_devices()
  238. *
  239. * Print a summary of all devices in the chain.
  240. */
  241.  
  242. list_devices()
  243. {
  244.  
  245. /*
  246. * Get the head of the device list.
  247. * If this isn't possible, print an error message and exit
  248. */
  249.  
  250.     if((current_device = device_chain()) == NULL)
  251.         no_device_chain() ;
  252.  
  253. /*
  254. * Print the column information
  255. */
  256.  
  257.     print_device_columns() ;
  258.  
  259. /*
  260. * Follow the chain until a -1 is reached
  261. */
  262.  
  263.     while(FP_OFF(current_device) != -1)
  264.     {
  265.         print_device_info(current_device) ;
  266.         current_device = current_device->next_hdr ;
  267.     }
  268.     printf("\nSystem has %d character drivers, and %d block drivers\n",
  269.         character_drivers,block_drivers) ;
  270. }
  271.  
  272. /*
  273. * Function: get_device()
  274. *
  275. * Find character or block device driver.
  276. * Fill in current device pointer, previous device pointer, and
  277. * current DPB if block device.
  278. *
  279. */
  280.  
  281. get_device(d)
  282. char d[] ;
  283. {
  284.     int i ;
  285.     char device_string[9] ;
  286.  
  287.     current_device = NULL ;
  288.     current_dpb = NULL ;
  289.     if(strlen(d) > 8)
  290.         return ;
  291.  
  292. /*
  293. * If there is a colon in the second character position, user
  294. * is requesting information about a block device.
  295. */
  296.  
  297.     if(d[1] != ':')
  298.     { 
  299.  
  300. /*
  301. * The name specified is probably a character device.
  302. * If a colon follows the device name, delete it from the string. 
  303. */
  304.  
  305.         if(d[strlen(d) - 1] == ':') /* kill colon at end of device name */
  306.             d[strlen(d) - 1] = 0 ;
  307. /*
  308. * Attempt to get the pointer to the first device in the chain.
  309. * if it comes back NULL, the user probably did not install the
  310. * trace device driver.
  311. */
  312.  
  313.         if((current_device = device_chain()) == NULL)
  314.             no_device_chain() ;  /* no device chain available */
  315.  
  316. /*
  317. * Trace the device chain until device name matches a
  318. * device in the chain
  319. */
  320.  
  321.         while(FP_OFF(current_device) != -1)
  322.         {
  323.             for(i = 0 ; i < 8 ; i++)
  324.                 device_string[i] = current_device->name[i] ;
  325.             device_string[8] = 0 ;
  326.             if(!strncmp(device_string,d,strlen(d)))
  327.                 if((strlen(d) == 8) ||
  328.                     (current_device->name[strlen(d)] == ' '))
  329.                     return ;
  330.             previous_device = current_device ;
  331.             current_device = current_device->next_hdr ;
  332.         }
  333.  
  334. /*
  335. * If no match, set the current device to NULL and return
  336. */
  337.  
  338.         current_device = NULL ;
  339.         return ;
  340.     }
  341.  
  342. /*
  343. * A colon was found in the second character position of the device
  344. * name, check for a valid block device.
  345. */
  346.  
  347.     else
  348.         is_disk = 1 ; /* set a flag to signify a disk device */
  349.  
  350.     if(strlen(d) > 2)    /* length must be less than or equal to 2 */
  351.         return ;
  352.  
  353. /*
  354. * Get the disk DPB for the drive specified.
  355. * If the disk doesn't exist, the current_dpb pointer will be
  356. * set to NULL, print a message and exit if this is the case.
  357. */
  358.  
  359.     if((current_dpb = disk_dpb(d[0] - 0x40)) == NULL)
  360.         no_disk_dpb() ;
  361.     current_device = current_dpb->dda ;
  362.     previous_device = NULL ;
  363.     return ;
  364. }        
  365.  
  366. /*
  367. * Function: print_device_columns()
  368. *
  369. * This function prints the headings and columns when listing
  370. * all device drivers.
  371. */
  372.  
  373. print_device_columns()
  374. {
  375.     printf("Base Address\t\t\tType\t\t\tName/Units\n") ;
  376.     printf("------------\t\t\t----\t\t\t----------\n") ;
  377. }
  378.  
  379. /*
  380. * Function: print_device_info()
  381. *
  382. * This function prints detailed information for a specific device.
  383. */
  384.  
  385. print_device_info(device)
  386. struct DEV_HDR far *device ;
  387. {
  388.     char device_string[9] ;
  389.     int i ;
  390.     printf("%04X:%04X\t\t\t",FP_SEG(device),FP_OFF(device)) ; /* print base address */
  391.     if(device->attribute & CHARACTER_DEVICE)
  392.     {
  393.         ++character_drivers ;
  394.         for(i = 0 ; i < 8 ; i++)
  395.             device_string[i] = device->name[i] ; /* copy it into local data segment */
  396.         device_string[8] = 0 ;
  397.         printf("Char\t\t\t%s\n",device_string) ; /* print "Char" and name */
  398.     }
  399.     else
  400.     {
  401.         ++block_drivers ;
  402.         printf("Block\t\t\t%u units\n",(int) device->name[0]) ;/* block dev.*/
  403.     }
  404. }
  405.  
  406. /*
  407. *
  408. * Function: disk_dpb()
  409. *
  410. * Return the address of the Disk Parameter Block (DPB) for the
  411. * drive specified. This DOS function is undocumented in current
  412. * DOS documentation. 
  413. */
  414.  
  415. struct DPB far *disk_dpb(drive)
  416. int drive ;
  417. {
  418.     char far *dsk_dpb ;
  419.  
  420.     ir.x.ax = 0x3200 ; /* Function call 32H */
  421.     ir.h.dl = drive ;
  422.     intdosx(&ir,&or,&sr) ;
  423.     if(++or.h.al == 0)
  424.         return (char far *) NULL ;
  425.     FP_SEG(dsk_dpb) = sr.ds ;
  426.     FP_OFF(dsk_dpb) = or.x.bx ;
  427.     return (struct DPB far *) dsk_dpb ;
  428. }
  429.  
  430. /*
  431. * Function: device_chain()
  432. *
  433. * Return the address of the first device in the device
  434. * chain.
  435. */
  436.  
  437.  
  438. struct DEV_HDR far *device_chain()
  439. {
  440.     struct DEV_HDR far *dev_chain ;
  441.     auto char far *search_ptr = (char far *) 0x00600000 ; /* start search at 0060:0000 */
  442.     static char *nuldev = "NUL     " ;
  443.     unsigned int x,i ;
  444.  
  445.     for(x = 0, i = 0 ; x < 65535 ; x++)
  446.     {
  447.         if(*search_ptr == *nuldev)    /* if first character matches, check others*/
  448.         {
  449.             for(i = 0 ; i <  8  ; i++)
  450.             {
  451.                 if(*(search_ptr + i) != nuldev[i])
  452.                     break ;
  453.             }
  454.             if(i == 8)      /* if i = 8 then the NUL device has been found */
  455.                 break ;
  456.         }
  457.         search_ptr++ ;
  458.     }
  459.     if(x == 0)
  460.         return NULL ;
  461.  
  462.     search_ptr -=  10 ; /* get to device header  */
  463.     return (struct DEV_HDR far *) search_ptr ;
  464. }
  465.  
  466. /*
  467. *
  468. * Function: no_device_chain()
  469. *
  470. * Print message "Can't find device chain" and exit
  471. */
  472.  
  473. no_device_chain()
  474. {
  475.     fprintf(stderr,"Can't find device chain\n") ;
  476.     exit(1) ;
  477. }
  478.  
  479. /*
  480. *
  481. * Function: no_disk_dpb()
  482. *
  483. * Print  message "Can't get DPB - Possible invalid drive\n" and exit
  484. */
  485.  
  486. no_disk_dpb()
  487. {
  488.     fprintf(stderr,"Can't get DPB - Possible invalid drive\n") ;
  489.     exit(1) ;
  490. }
  491.